use core::ffi::c_void;

use crate::{guid_struct, EfiStatus};

use super::{task::EfiTpl, EfiGuid};

pub type EfiEvent = *mut c_void;

pub type EfiCreateEvent = extern "efiapi" fn(
    event_type: u32,
    notify_tpl: EfiTpl,
    notify_function: EfiEventNotify,
    notify_context: *mut c_void,
    event: *mut EfiEvent,
) -> EfiStatus;
pub type EfiEventNotify = extern "efiapi" fn(event: EfiEvent, context: *mut c_void);
pub type EfiCreateEventEx = extern "efiapi" fn(
    event_type: u32,
    notify_tpl: EfiTpl,
    notify_function: EfiEventNotify,
    notify_context: *mut c_void,
    event_group: *const EfiGuid,
    event: *mut EfiEvent,
) -> EfiStatus;
pub type EfiCloseEvent = extern "efiapi" fn(event: EfiEvent) -> EfiStatus;
pub type EfiSignalEvent = extern "efiapi" fn(event: EfiEvent) -> EfiStatus;

/// ### 参数
/// + number_of_events: event 数组中元素的数量
/// + event: [`EfiEvent`] 类型的数组，EfiEvent 可以通过 `CreateEvent` 函数来创建
/// + index: 指针，指向满足等待条件的事件的索引。
pub type EfiWaitForEvent = extern "efiapi" fn(
    number_of_events: usize,
    event: *const EfiEvent,
    index: *mut usize,
) -> EfiStatus;
pub type EfiCheckEvent = extern "efiapi" fn(event: EfiEvent) -> EfiStatus;
pub type EfiSetTimer =
    extern "efiapi" fn(event: EfiEvent, time_type: EfiTimerDelay, trigger_time: u64) -> EfiStatus;

#[non_exhaustive]
#[derive(PartialEq, PartialOrd, Eq, Debug)]
#[repr(C)]
pub enum EfiTimerDelay {
    TimerCancel,
    TimerPeriodic,
    TimerRelative,
}

pub const EVT_TIMER_MASK: u32 = 0x80000000;
pub const EVT_RUNTIME_MASK: u32 = 0x40000000;
pub const EVT_NOTIFY_WAIT_MASK: u32 = 0x00000100;
pub const EVT_NOTIFY_SIGNAL_MASK: u32 = 0x00000200;
pub const EVT_SIGNAL_EXIT_BOOT_SERVICES: u32 = 0x00000201;
pub const EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE_MASK: u32 = 0x60000202;

pub const EFI_EVENT_GROUP_EXIT_BOOT_SERVICES: EfiGuid =
    guid_struct! {0x27abf055, 0xb1b8, 0x4c26, {0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf}};
pub const EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES: EfiGuid =
    guid_struct! {0x8be0e274, 0x3970, 0x4b44, {0x80, 0xc5, 0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc}};
pub const EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE: EfiGuid =
    guid_struct! {0x13fa7698, 0xc831, 0x49c7, {0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96}};
pub const EFI_EVENT_GROUP_MEMORY_MAP_CHANGE: EfiGuid =
    guid_struct! {0x78bee926, 0x692f, 0x48fd, {0x9e, 0xdb, 0x1, 0x42, 0x2e, 0xf0, 0xd7, 0xab}};
pub const EFI_EVENT_GROUP_READY_TO_BOOT: EfiGuid =
    guid_struct! {0x7ce88fb3, 0x4bd7, 0x4679, {0x87, 0xa8, 0xa8, 0xd8, 0xde,0xe5,0xd, 0x2b}};
pub const EFI_EVENT_GROUP_AFTER_READY_TO_BOOT: EfiGuid =
    guid_struct! {0x3a2a00ad, 0x98b9, 0x4cdf, {0xa4, 0x78, 0x70, 0x27, 0x77, 0xf1, 0xc1,0xb }};
pub const EFI_EVENT_GROUP_RESET_SYSTEM: EfiGuid =
    guid_struct! {0x62da6a56, 0x13fb, 0x485a, {0xa8, 0xda, 0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b}};
